package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.exception.StgyException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.util.IpUtils;
import com.atguigu.lease.common.util.JwtUtil;
import com.atguigu.lease.web.admin.dto.AdminLoginDto;
import com.atguigu.lease.web.admin.dto.SystemUserSearchDto;
import com.atguigu.lease.web.admin.mapper.SystemUserMapper;
import com.atguigu.lease.web.admin.service.SystemPostService;
import com.atguigu.lease.web.admin.vo.AdminCaptchaVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.lease.model.entity.SystemUser;
import com.atguigu.lease.web.admin.service.SystemUserService;
import com.wf.captcha.GifCaptcha;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.annotation.Resource;
import org.joda.time.DateTime;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 1
 * @description 针对表【system_user(员工信息表)】的数据库操作Service实现
 * @createDate 2024-08-28 11:00:26
 */
@Service
public class SystemUserServiceImpl extends ServiceImpl<SystemUserMapper, SystemUser>
        implements SystemUserService {
    @Resource
    SystemPostService systemPostService;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Override
    public Page<SystemUser> getPage(SystemUserSearchDto searchDto) {
        Page<SystemUser> page = this.page(searchDto.getPage(SystemUser.class),
                Wrappers.lambdaQuery(SystemUser.class)
                        .like(StringUtils.hasLength(searchDto.getName()),
                                SystemUser::getName, searchDto.getName())
                        .like(StringUtils.hasLength(searchDto.getPhone()),
                                SystemUser::getPhone, searchDto.getPhone()));

        page.getRecords().forEach(systemUser -> {
            //查询每个管理员的岗位信息
            systemUser.setPostName(systemPostService.getById(systemUser.getPostId()).getName());
        });
        return page;
    }

    @Override
    public boolean saveOrUpdateSystemUser(SystemUser systemUser) {
        try {
            long id = systemUser.getId()==null?-1l:systemUser.getId();
            SystemUser dbSystemUser = this.getOne(Wrappers.lambdaQuery(SystemUser.class)
                    .eq(SystemUser::getUsername, systemUser.getUsername())
                    .or()
                    .eq(SystemUser::getPhone, systemUser.getPhone())
                    .last("limit 1"));
            if(dbSystemUser!=null && id != dbSystemUser.getId() ){
                throw new StgyException(ResultCodeEnum.DATA_EXISTS_ERROR);
            }
            //新增时 设置默认头像
            if(systemUser.getId() == null){
                systemUser.setAvatarUrl("https://element-plus.org/images/element-plus-logo.svg");
                systemUser.setStatus(1);//默认新增的账号 可用
            }
            //密码加密：   以后的加密可以使用 加盐(salt 就是一个随机的字符串)的方式来处理
            String encodedPwd = DigestUtils.md5DigestAsHex(systemUser.getPassword().getBytes("UTF-8"));
            systemUser.setPassword(encodedPwd);
            return this.saveOrUpdate(systemUser);
        } catch (Exception e) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR,e);
        }
    }

    @Override
    public AdminCaptchaVo getCaptcha() {
        //1、生成验证码
        GifCaptcha gifCaptcha = new GifCaptcha(120,40 , 4);
        //2、组装响应数据
        AdminCaptchaVo captchaVo = new AdminCaptchaVo();
        captchaVo.setImage(gifCaptcha.toBase64());
        String key = UUID.randomUUID().toString().replace("-", "");
        captchaVo.setKey(key);
        //gifCaptcha.text()
        //3、服务器缓存验证码  以后登录校验使用
        stringRedisTemplate.opsForValue().set("stgy:admin:code:"+key,gifCaptcha.text(),
                5 , TimeUnit.MINUTES);

        return captchaVo;
    }

    @Override
    public String login(AdminLoginDto loginDto) {
        String username = loginDto.getUsername();
        String password = loginDto.getPassword();
        String captchaCode = loginDto.getCaptchaCode();
        String captchaKey = loginDto.getCaptchaKey();
        //校验参数：不能为空
        if(StringUtils.isEmpty(username) ||
                StringUtils.isEmpty(password) ||
                StringUtils.isEmpty(captchaCode) ||
                StringUtils.isEmpty(captchaKey)
        ){
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        //验证码校验
        //1、获取redis验证码缓存
        String cacheCode = stringRedisTemplate.opsForValue().get("stgy:admin:code:" + captchaKey);
        //2 校验验证码
        if(!captchaCode.equalsIgnoreCase(cacheCode)){
            throw new StgyException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_ERROR);
        }
        //校验账号
        SystemUser systemUser = this.getOne(Wrappers.lambdaQuery(SystemUser.class)
                .eq(SystemUser::getUsername, username)
                .last("limit 1"));
        if(ObjectUtils.isEmpty(systemUser)){
            throw new StgyException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }
        //校验密码
        //1、对前端提交的明文加密
        String encodedPwd = DigestUtils.md5DigestAsHex(password.getBytes());
        //2、比较密码：  MD5加密相同明文每次加密的结果一样，  Bcrypt方式加密 相同明文加密的结果不同，校验时需要调用它自己的方法来比较
        if(!encodedPwd.equals(systemUser.getPassword())){
            throw new StgyException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }
        //删除redis缓存的验证码：
        stringRedisTemplate.delete("stgy:admin:code:" + captchaKey);
        //动态获取请求对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //将登录成功的用户信息创建为jwttoken
        return JwtUtil.createToken(systemUser,requestAttributes.getRequest());//按照上面的配置构建 jwt 字符串
    }
}




